home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
dev
/
c
/
vbcc.lha
/
vbcc
/
pasm
/
pass.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-17
|
13KB
|
474 lines
/* $VER: pasm pass.c V0.8 (14.02.98)
*
* This file is part of pasm, a portable PowerPC assembler.
* Copyright (c) 1997-98 Frank Wille
*
* pasm is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
* pasm may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v0.8 (14.02.98) phx
* Alignment list for each section. This fixes the problems
* with optimizations.
* v0.7 (02.01.98) phx
* Allow more than two assembler passes, as required for
* optimizations.
* v0.6 (26.10.97) phx
* Bug in conditional assembly fixed.
* @object and @function symbols are always defined before
* pass 1 is executed.
* v0.5 (12.10.97) phx
* Support for user symbol definitions by -D option.
* The opcode field is automatically converted to lower case,
* so upper case directives and instructions are also allowed.
* v0.3 (10.04.97) phx
* Some vbcc-specific changes.
* v0.2 (25.03.97) phx
* Writes ELF object for 32-bit PowerPC big-endian. Either absolute
* or ELF output format may be selected. ELF is default for all
* currently supported platforms. PPCasm supports nine different
* relocation types (there are much more...).
* Compiles and works also under NetBSD/amiga (68k).
* Changed function declaration to 'new style' in all sources
* (to avoid problems with '...' for example).
* v0.1 (11.03.97) phx
* First test version with all PowerPC instructions and most
* important directives. Only raw, absolute output.
* v0.0 (15.02.97) phx
* File created.
*/
#define PASS_C
#include "ppcasm.h"
void exec_pass1(struct GlobalVars *);
void pass1(struct GlobalVars *,struct SourceText *,
struct MacroParams *,struct SourceThread *);
struct SourceText *include_source(struct GlobalVars *,char *);
void exec_pass2(struct GlobalVars *);
void pass2(struct GlobalVars *,struct SourceText *,
struct MacroParams *,struct SourceThread *);
struct SourceText *get_source(struct GlobalVars *);
static char *insert_macro_params(struct GlobalVars *,struct ParsedLine *,
char *,struct MacroParams *);
static char *readline(struct GlobalVars *,struct ParsedLine *,char *);
static char *getlabel(struct GlobalVars *,char *);
static struct SourceText *add_source(struct GlobalVars *,char *,char *,long);
static void prepare_sections(struct GlobalVars *);
void exec_pass1(struct GlobalVars *gv)
{
struct Symbol *sym;
char asmname[20];
char **p,*xmnemobuf,*usrdefbuf;
size_t xmsize=0,udsize=0;
struct UserDefine *nextudn;
struct UserDefine *udn = (struct UserDefine *)gv->userdeflist.first;
struct Section dummySec;
sprintf(asmname,PNAME "_V%d.%02d",VERSION,REVISION);
memset(&dummySec,0,sizeof(struct Section));
gv->csect = &dummySec; /* to avoid SEGVs during start up */
sym = add_symbol(gv,asmname,SYM_ABS,0);
sym->bind = SYMB_LOCAL;
gv->lcsym = add_symbol(gv,"$",SYM_RELOC,0);
gv->nargsym = add_symbol(gv,"$NARG",SYM_ABS,0);
add_symbol(gv,"@object",SYM_ABS,1);
add_symbol(gv,"@function",SYM_ABS,2);
gv->ifcond[0] = TRUE;
pass1(gv,add_source(gv,"<standard sections>",stdsects,
strlen(stdsects)),NULL,NULL);
if (!gv->noregsymbols)
pass1(gv,add_source(gv,"<standard definitions>",stdsets,
strlen(stdsets)),NULL,NULL);
while (nextudn = (struct UserDefine *)udn->n.next) {
udsize += strlen(udn->line);
udn = nextudn;
}
if (udsize) {
usrdefbuf = alloc(udsize+1);
*usrdefbuf = 0;
while (udn = (struct UserDefine *)remhead(&gv->userdeflist)) {
strcat(usrdefbuf,udn->line);
free(udn->line);
free(udn);
}
gv->usrdefs = TRUE;
pass1(gv,add_source(gv,"<user definitions>",usrdefbuf,udsize),
NULL,NULL);
}
if (!gv->noextmnemo) {
p = xmnemos;
while (*p) {
xmsize += strlen(*p);
p++;
}
xmnemobuf = alloc(xmsize+1);
*xmnemobuf = 0;
p = xmnemos;
while (*p) {
strcat(xmnemobuf,*p);
p++;
}
pass1(gv,add_source(gv,"<extended mnemonics>",xmnemobuf,xmsize),
NULL,NULL);
}
pass1(gv,include_source(gv,gv->source_name),NULL,NULL);
if (gv->vc) {
activate_section(gv,(struct Section *)gv->sectionlist.first);
alignment(gv,2);
pcadd(gv,4);
}
}
void pass1(struct GlobalVars *gv,struct SourceText *srctxt,
struct MacroParams *macro,struct SourceThread *prev_st)
/* Assembler Pass 1 */
{
struct SourceThread st;
unsigned long nlines = srctxt->nlines;
char *lp,c;
struct ParsedLine *pl = srctxt->plin;
/* init SourceThread structure */
st.prev = prev_st;
st.macro = macro;
st.csource = srctxt;
st.srcptr = srctxt->text; /* current source pointer */
st.line = 1;
st.macskip = NULL;
gv->cthread = &st; /* set current source thread */
while (nlines--) {
gv->absline++;
pl->lineptr = st.lineptr = st.srcptr;
/* get next line of source text */
if (macro && gv->ifcond[gv->iflevel]) { /* insert macro parameters? */
st.srcptr = insert_macro_params(gv,pl,st.srcptr,macro);
}
else {
st.srcptr = readline(gv,pl,st.srcptr);
}
lp = gv->linebuf;
/* evaluate label field */
lp = getlabel(gv,lp);
if (*gv->strbuf)
if (!st.macskip && gv->ifcond[gv->iflevel])
add_symbol(gv,gv->strbuf,SYM_RELOC,gv->csect->pc);
lp = skipspaces(lp);
/* evaluate opcode field */
lp = getsymbol(gv,lp);
if (*gv->strbuf) {
lower_case(gv->strbuf); /* convert opcode to lower case */
if (st.macskip) { /* macros */
if (!strcmp(gv->strbuf,".endm")) {
st.macskip->nlines = gv->absline - st.macskip->nlines;
add_macro(gv,st.macskip);
st.macskip = NULL;
}
}
else if (!gv->ifcond[gv->iflevel]) { /* conditional assembly */
if (!strncmp(gv->strbuf,".if",3))
gv->ifignore++;
else if (!strcmp(gv->strbuf,".else")) {
if (gv->ifignore == 0)
gv->ifcond[gv->iflevel] = TRUE;
}
else if (!strcmp(gv->strbuf,".endif")) {
if (gv->ifignore)
gv->ifignore--;
else
gv->iflevel--;
}
}
else { /* search opcode */
c = *lp; /* branch hint given? */
if (c=='+') {
lp++;
pl->branch_hint = 1;
}
else if (c=='-') {
lp++;
pl->branch_hint = -1;
}
search_opcode(gv,pl,gv->strbuf,skipspaces(lp));
}
}
if (!(pl->flags&PLF_NONEWLINE))
st.line++;
++pl;
}
gv->cthread = prev_st;
}
static char *insert_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
char *s,struct MacroParams *mp)
{
char **par = mp->param;
char c,callidbuf[16];
char *pp,*d=gv->linebuf;
int n;
do {
if ((c=*s++) == '\\') {
if (*s>='0' && *s<='9') { /* macro parameter? */
n = (int)(*s++ - '0');
if (pp = par[n]) {
while (*d++ = *pp++); /* insert parameter */
d--;
continue;
}
else {
error(9,n); /* reference to undefined macro parameter n */
continue;
}
}
else if (*s=='@') { /* insert macro call id */
s++;
pp = callidbuf;
sprintf(pp,"$%d",(int)mp->call_id);
while (*d++ = *pp++);
d--;
continue;
}
}
*d++ = c;
}
while (c!=0 && c!=1);
if (c==1) {
*(--d) = 0;
pl->flags |= PLF_NONEWLINE;
}
return (s);
}
static char *readline(struct GlobalVars *gv,struct ParsedLine *pl,char *s)
{
char c,*d = gv->linebuf;
do {
c = *s++;
*d++ = c;
}
while (c!=0 && c!=1);
if (c==1) {
*(--d) = 0;
pl->flags |= PLF_NONEWLINE;
}
return (s);
}
static char *getlabel(struct GlobalVars *gv,char *s)
/* read label